package sweet.mvc.api

/** A View object is used to represent a view name and map of models.
 *
 * The models will be merge into request scope automatically by the dispatcher
 * when rendering the view. 
 *
 * Each action handler in a controller must return an instance of View. 
 */
sealed case class View(name: String, models: Map[String, Any]){
  def this(name: String) = this(name, Map.empty[String, Any])
  def this(name: String, tuples: (String, Any)*) = this(name, Map()++tuples)
}
object View{  
  def apply(name: String) = new View(name)
  def apply(name: String, tuples: (String, Any)*) = new View(name, tuples: _*)
  
  /** recreate view object and append models base on it's type */
  def apply(view: View, _models: Map[String, Any]): View = {
    view match {
      case v: EmptyView => EmptyView()
      case v: HandlerNameView => HandlerNameView(view.models ++ _models)
      case _  => apply(view.name, view.models ++ _models)
    }
  }
}

/** A View that will automatically figure out the name based on incoming
 * URL of action handler name */
case class HandlerNameView(m: Map[String, Any]) extends View("/AUTO_RESOLVED_HANLDER_NAME", m){
  def this(tuples: (String, Any)*) = this(Map()++tuples)  
}
object HandlerNameView{  
  def apply(tuples: (String, Any)*) = new HandlerNameView(tuples: _*)
}

/** An empty view is needed to signal the dispatcher that User has handled
 * the response themself and the framework should not do any output. 
 */
case class EmptyView extends View(null)

